<?php

namespace App\Http\Controllers\Admin\ExportReport;

use Dompdf\Exception;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use DB;
use PhpOffice\PhpWord\IOFactory;
use Storage;

class ExportReportGanSuBaiYinController extends Controller
{
    protected $sourceDir = './storage/ExcelTemplate/GanSuBaiYin/';
    private $disk=null;
    private $storeFile='';
    protected static $resCode = [0=>'不合格',1=>'合格',2=>'不合格',3=>'未试验'];

    /**
     * 批量导出Word 检测报告
     * @param Request $request
     * @return string
     * @throws \PhpOffice\PhpWord\Exception\CopyFileException
     * @throws \PhpOffice\PhpWord\Exception\CreateTemporaryFileException
     * @throws \PhpOffice\PhpWord\Exception\Exception
     */
    public function export(Request $request)
    {
        @set_time_limit(0);
        //ini_set('pcre.backtrack_limit', 999999999);
        ini_set('max_execution_time', 0);
        ini_set('memory_limit', "-1");
        $contract_id = (int)$request->id; //批次 id
        $setting = DB::table('setting')->find(1); //
        $report_num_pre = $setting->report_num_pre; //报告编号前缀
        $company_name = $setting->name_rep; //获取检测公司名称
        $data_batch = DB::table('a_contract')->find($contract_id);
        $batchNum = $data_batch->batchNum;

        //文件存在直接下载
        $downFile = 'reports/'.$batchNum.'.zip';
        $this->disk = Storage::disk('public');
        if($this->disk->exists($downFile) && $data_batch->status > 13 ){
            return $this->disk->download($downFile);
        }

        //查询当前批次下所有工器具类型
        $sql = "SELECT DISTINCT tool_id,tool_name,unit
                FROM a_contract_gaiyao WHERE contract_id ={$contract_id}";
        //判断是否有针对性的工器具下载
        if($request->tid) {
            $sql = $sql." and tool_id in ($request->tid)";
        }
        $tool_group = DB::select($sql);
        //大循环-循环获取工器具
        foreach ($tool_group as $tkey => $tval) {
            try{
            $template_file = "./storage/ExcelTemplate/GanSuBaiYin/{$tval->tool_name}.docx"; //考虑到兼容Linux，斜杠用“/”
            if (!file_exists($template_file)) {
                //为了防止内存泄漏，建议用完手动清理
                return "{$tval->tool_name}的word模板文件不存在";
            }
            //公共变量
            $sample_info = DB::table('a_contract_gaiyao as g')
                ->leftJoin('a_sample_info as s', 's.contract_gaiyao_id', '=', 'g.id')
                ->select('s.*', 'g.tool_name', 'g.unit','g.std_id','g.tool_id','g.class_id','g.vol_id')
                ->where('g.tool_id', $tval->tool_id)->where('g.contract_id',$contract_id)->get()->map(function ($value) {
                    return (array)$value;
                })->toArray();
            if ($sample_info) {
                $guige_xinghao = implode(',', array_unique(array_column($sample_info, 'guige_xinghao')));
                $sample_id_arr = array_column($sample_info, 'id');
                $sample_id_str = implode(',', array_column($sample_info, 'id'));
                $gaiyao_id_arr = array_column($sample_info, 'contract_gaiyao_id');
            }else{
                return '样品不存在！';
            }
            //检测设备
            $dev_name = '';
            $fac_num = '';
            $dev_num = '';
            $station_ids = [];
            $test_item_data = DB::table('a_item_data')->whereIn('sample_info_id', $sample_id_arr)->where('item_id', '!=', 61)->get();
            foreach ($test_item_data as $kdev => $devv) {
                $station_ids = array_merge($station_ids, explode(',', $devv->station_ids));
                $station_ids = array_unique($station_ids);
            }
            $devInfo = DB::table('a_station')->whereIn('id', $station_ids)->select('fac_num', 'dev_num', 'name')->get()->toArray();
            if ($devInfo) {
                $dev_name = implode(',', array_column($devInfo, 'name'));
                $fac_num = implode(',', array_column($devInfo, 'fac_num'));
                $dev_num = implode(',', array_column($devInfo, 'dev_num'));
            }
            //检验日期开始时间
            $testdate_start = DB::table('a_sample_info as B')->leftJoin('a_item_data as A', 'A.sample_info_id', '=', 'B.id')->whereIn('B.id', $sample_id_arr)->min('test_time');
            //检验日期结束时间
            $testdate_end = DB::table('a_sample_info as B')->leftJoin('a_item_data as A', 'A.sample_info_id', '=', 'B.id')->whereIn('B.id', $sample_id_arr)->max('test_time');
            //试验依据
            $std_arr = DB::table('a_contract_gaiyao')->select('std_id')->where('tool_id',$tval->tool_id)->groupBy('std_id')->get()->map(function ($value) {
                return (array)$value;
            })->toArray();
            $std_id_arr = array_column($std_arr, 'std_id');
            $standards = DB::table('a_standard')->whereIn('id', $std_id_arr)->get()->map(function ($value) {
                return (array)$value;
            })->toArray();
            $standstr = '';
            foreach($standards as $sk=>$sv){
                $standstr .= $sv['num'].'《' .$sv['name'].'》'.'; ';
            }
            $temp_hum_sqs = "select max(temp) as maxtemp,max(hum) as maxhum,max(pressure) as maxpressure from a_item_data where temp != '' and hum !='' and sample_info_id in ({$sample_id_str})";
            $temp_hum_data = DB::select($temp_hum_sqs);
            //签发日期
            if($data_batch->deadline) {
                $year = date('Y', strtotime($data_batch->deadline));
                $month = date('m', strtotime($data_batch->deadline));
                $day = date('d', strtotime($data_batch->deadline));
            }
            //公共变量
            $values = [
                'test_name' => $tval->tool_name,
                'batchNum' => $sample_info[0]['batch_num_custom'],
                'bar_code' => $batchNum,
                'test_guige' => $guige_xinghao,
                'entrusted_company' => $data_batch->entrusted_company,
                //'test_addr' => $data_batch->test_address,
                'test_addr' => '中国 甘肃 白银市白银区刘家梁170号',
                'entrustNum' => $data_batch->letter_no,           //委托编号
                'test_type' => $data_batch->test_kind,
                'company_name' => $company_name,
                'report_end' => $data_batch->deadline?date('Y年m月d日', strtotime($data_batch->deadline)):'',
                'yp_date' => date('Y.m.d', strtotime($data_batch->created_at)),
                'test_start_date' => date('Y.m.d', strtotime($testdate_start)),
                'test_end_date' => $data_batch->deadline?date('Y.m.d', strtotime($data_batch->deadline)):'',
                'standards' => rtrim($standstr,'; '),
                'client_name' => $data_batch->client_name,
                'number' => count($sample_info) . $sample_info[0]['unit'],
                'pressure' => $temp_hum_data[0]->maxpressure,
                'temp' => $temp_hum_data[0]->maxtemp,
                'humi' => $temp_hum_data[0]->maxhum,
                'station_name' => $dev_name,
                'fac_num' => $fac_num,
                'dev_num' => $dev_num,
                'year'=>isset($year)?$year:'',
                'month'=>isset($month)?$month:'',
                'day'=>isset($day)?$day:'',
                'remark'=>'无',
                'sc_date'=>'/',
            ];
            #dd($values);
            //加载模板类
            $template = new \PhpOffice\PhpWord\TemplateProcessor($template_file);
            //为模板中的变量赋值
            $template->setValues($values);
            //审核批准编制人名章
            if($sample_info[0]['tester_names']){
                $test_arr = explode('，',$sample_info[0]['tester_names']);
                $shen_man = isset($test_arr[0])?$test_arr[0]:'';
                $bian_man = isset($test_arr[1])?$test_arr[1]:'';
            }
            $signs = [
                'pi_man'=>"storage/images/managers/展飞.png",
                'shen_man'=>"storage/images/managers/{$shen_man}.png",
                'bian_man'=>"storage/images/managers/{$bian_man}.png",
            ];
            foreach ($signs as $var => $sign) {
                file_exists($sign) ? $template->setImageValue($var, ["path" => $sign, "height" => 50]) : '';
            }
            //检验结果汇总
            $sql = "SELECT DISTINCT i.item_id,i.res,t.name FROM a_item_data as i left join a_testitem as t on t.id=i.item_id WHERE sample_info_id in ({$sample_id_str})";
            $item_info = DB::select($sql);
            $rows = count($item_info);
            $template->cloneRow('item_id',$rows);
            foreach ($item_info as $key => $val) {
                $sample_self_num_str = '';
                if($val->res == 0 || $val->res == 2) {
                    $sample_self_num = DB::table('a_item_data as i')
                        ->leftJoin('a_sample_info as s', 's.id', '=', 'i.sample_info_id')
                        ->select('s.self_num')->where('i.item_id', $val->item_id)->where('i.res', $val->res)
                        ->whereIn('i.contract_gaiyao_id', $gaiyao_id_arr)
                        ->get()->map(function ($value) {
                            return (array)$value;
                        })->toArray();
                    if ($sample_self_num) {
                        $sample_self_num_str = implode(',', array_unique(array_column($sample_self_num, 'self_num')));
                    }
                }
                $no = $key + 1;
                $template->setValue("item_id#".$no,$no);
                $template->setValue("item_name#".$no,$val->name.' '.$sample_self_num_str);
                $template->setValue("item_result#".$no,'详见报告正文');
                $resmsg = self::$resCode[$val->res];
                $template->setValue("item_res#".$no,$resmsg);
            }
            //报告正文-外观检查
            $waiguanArr = [];
            $waiguanArr = DB::table('a_item_data as i')
                ->leftJoin('a_sample_info as s', 's.id', '=', 'i.sample_info_id')
                ->leftJoin('a_contract_gaiyao as c','c.id','=','s.contract_gaiyao_id')
                ->select('i.res', 'i.item_id', 's.bar_code','c.std_id','c.tool_id','s.self_num')->whereIn('i.sample_info_id', $sample_id_arr)->whereIn('item_id', [61,84])->get();
            $wrows = count($waiguanArr);
            $template->cloneRow('wai_no',$wrows);
            foreach ($waiguanArr as $wkey => $wval) {
                $waiguanyaoqiu = DB::table('a_std_tool_item_rel')->where('std_id', $wval->std_id)->where('tool_id', $wval->tool_id)->where('testitem_id', $wval->item_id)->first();
                $wno = $wkey + 1;
                $template->setValue("wai_no#".$wno,$wno);
                $template->setValue("wai_bar_code#".$wno,$wval->self_num);
                $template->setValue("wai_yaoqiu#".$wno,$waiguanyaoqiu->jishu_yaoqiu);
                $resmsg = self::$resCode[$wval->res];
                $template->setValue("wai_item_res#".$wno,$resmsg);
                $template->setValue("wai_conclusion#".$wno,$resmsg);
            }
            //报告正文-试验数据---以试验项目为基准，不能以样品
            $item_input_data_arr = [];
            $input_data = DB::table('a_input_data as i')
                ->leftJoin('a_testdata_key as t','i.testdata_key_id','=','t.id')
                ->leftJoin('a_std_tool_item_rel as r','t.std_tool_item_rel_id','=','r.id')
                ->select('i.val','i.sample_info_id','t.item_id','t.pos_end','t.pos_start','r.pos_start as rpos_start','r.pos_end as rpos_end')
                ->whereIn('i.sample_info_id',$sample_id_arr)->where('t.item_id','!=',84)        //剔除外观及尺寸(84)，试验数据，将他归到外观检查里
                ->get()->map(function ($value) {
                    return (array)$value;
                })->toArray();
            $item_data = DB::table('a_item_data')->whereIn('sample_info_id',$sample_id_arr)->where('item_id','!=',61)->get()->toArray();
            if ($item_data) {
                $item_id_arr = array_column($item_data, 'item_id');
                $item_id_arr = $this->array_duplicate($item_id_arr);
            }
            /* 样例：
              array (
                  6 => array (
                    3 => array (
                          'AG6AM' => '2.5',
                          'BB6BH' => '0.08',
                          'AN6AT' => '1',
                          'AU6BA' => '0.08',
                            种类，
                            电压，
                        ),
                    5 => array (
                          'AG6AM' => '2.5',
                          'BB6BH' => '0.06',
                          'AN6AT' => '1',
                          'AU6BA' => '0.06',
                            种类，
                            电压，
                        ),
                    ),
                  7 => array (
                    3 => array (
                          'BI7BP' => '0.04',
                          'BJ7BP' => '0.04',
                            种类，
                            电压，
                        ),
                    5 => array (
                          'BI7BP' => '0.03',
                          'BJ7BP' => '0.03',
                            种类，
                            电压，
                        ),
                    ),
                )
            */
            foreach($item_id_arr as $iikey=>$iival){
                foreach($sample_info as $sikey=>$sival) {
                    foreach ($input_data as $idkey => $idval) {
                        if ($iival == $idval['item_id']) {      //二维数组-》项目id为键值
                            if($sival['id'] == $idval['sample_info_id']) {    //三维数组-》样品id为键值
                                $itemRes = DB::table('a_item_data')->where('sample_info_id',$idval['sample_info_id'])->where('item_id',$idval['item_id'])->first();
                                $item_resmsg = self::$resCode[$itemRes->res];
                                //拼装公共参数
                                $item_input_data_arr[$iival][$sival['id']]['bar' . $idval['item_id'] . 'no'] = $sikey+1; //序号
                                $item_input_data_arr[$iival][$sival['id']]['bar' . $idval['item_id'] . 'code'] = $sival['self_num']; //编号
                                $item_input_data_arr[$iival][$sival['id']]['next' . $idval['item_id'] . 'time'] = $sival['next_time']; //编号
                                //试验数据
                                $item_input_data_arr[$iival][$sival['id']][$idval['pos_start'] . $idval['item_id'] . $idval['pos_end']] = $idval['val']; //试验数据与位置
                                $item_input_data_arr[$iival][$sival['id']][$idval['rpos_start'] . $idval['item_id'] . $idval['rpos_end']] = $item_resmsg;//结论与位置
                                //种类
                                if($sival['class_id']){
                                    $classInfo = DB::table('a_voltage_class as v')
                                        ->leftJoin('a_excel_pos as e','v.std_tool_rel_id','=','e.std_tool_rel_id')
                                        ->select('v.val','e.class1','e.class2')->where('v.id',$sival['class_id'])->where('e.is_default',1)->first();
                                    $item_input_data_arr[$iival][$sival['id']][$classInfo->class1 . $idval['item_id'] . $classInfo->class2] = $classInfo->val;
                                }
                                //电压
                                if($sival['vol_id']){
                                    $volInfo = DB::table('a_voltage_class as v')
                                        ->leftJoin('a_excel_pos as e','v.std_tool_rel_id','=','e.std_tool_rel_id')
                                        ->select('v.val','e.voltage1','e.voltage2')->where('v.id',$sival['vol_id'])->where('e.is_default',1)->first();
                                    $item_input_data_arr[$iival][$sival['id']][$volInfo->voltage1 . $idval['item_id'] . $volInfo->voltage2] = $volInfo->val;
                                }
                            }
                        }
                    }
                }
            }
            #dd($item_input_data_arr);
            foreach($item_input_data_arr as $iidkey=>$iidval){
                $rowNo = 1;
                $iidrow = count($iidval);
                $template->cloneRow("bar{$iidkey}no",$iidrow);
                foreach($iidval as $kkk=>$vvv){
                    foreach($vvv as $k=>$v){
                        $template->setValue($k.'#'.$rowNo,$v);
                        $template->setValue("item_id#".$no,$no);

                    }
                    $rowNo++;
                }
            }
            //获取该样品的所有标准下的试验项目id,并去重
            $allItemId_arr = [];
            $allItemId = DB::table('a_std_tool_item_rel')->select('testitem_id')
                ->where('tool_id',$tval->tool_id)->where('ishide',0)->where('testitem_id','!=',61)
                ->groupBy('testitem_id')
                ->get()->map(function ($value) {
                    return (array)$value;
                })->toArray();
            if($allItemId){
                $allItemId_arr = array_column($allItemId,'testitem_id');
            }
            //后删除模块-循环删除
            $diff_itemId = array_diff($allItemId_arr,$item_id_arr);
            if($diff_itemId){
                foreach($diff_itemId as $dkey=>$dval){
                    $template->deleteBlock("item_{$dval}");
                }
            }
            //将无值的变量置空
            $emptyVars = $template->getVariables();
            foreach ($emptyVars as $emptyVar) {
                $template->setValue($emptyVar,'');
            }
            //保存目录
            $this->storeFile = "reports/$batchNum/" . $tval->tool_name . '.docx';
            $this->saveDown($template,$sample_info);
            } catch(\Exception $exception) {
                dd($exception->getMessage(),$tval->tool_name.'-报告模板有问题！',$item_input_data_arr);
            }
        }
        //这里进行打包下载
        $saveZipFile = './storage/reports/'.$batchNum.'.zip';
        $zip = new \ZipArchive();
        $zip->open($saveZipFile,\ZipArchive::CREATE);
        foreach($tool_group as $tgkry=>$tgval){
            $file = "./storage/reports/{$batchNum}/{$tgval->tool_name}.docx";
            $zip->addFile($file,basename($file));
        }
        $zip->close();

        if($data_batch->status > 13) {
            return response()->download($saveZipFile);
        }else{
            return response()->download($saveZipFile)->deleteFileAfterSend(true);
        }

        #end
    }

    /**
     * 不是下载，批量是直接保存docx文件
     * @param $templateProcessor
     * @param $sample_info
     */
    private function saveDown($templateProcessor,$sample_info){
        $disk = $this->disk;
        $storeFile = $this->storeFile;
        try{
            $disk->put($storeFile,''); //创建路径
            $templateProcessor->saveAs($disk->path($storeFile));
        }catch(Exception $e){
            $disk->delete($storeFile);
        }
    }

    //二维数据去重
    public function array_duplicate($arr){
        $tmp = array();
        $result = array();
        $result_arr = [];
        $i = 0;
        foreach($arr as $key => $val){
            $tmp[$key] = json_encode($val);
        }
        unset($val);
        $final = array_unique($tmp);
        foreach($final as $key => $val){
            $result[$key] = json_decode($val, true);
        }
        //序号重组
        foreach($result as $kk=>$vv){
            $result_arr[$i] = $vv;
            $i++;
        }

        return $result_arr;
    }

    //字符串转数组去重
    private function getUnique($source,$glue='，',$array = false){
        if (is_string($source)) {
            $source = explode($glue,$source);
        }
        $source = explode($glue,implode($glue, $source));
        if ($array) {
            return array_unique($source);
        }
        $source = implode($glue,array_unique($source));
        return $source;
    }

}
